#include "StdAfx.h"
#include "HotKeyManager.h"
#include "HotKeyCompare.h"
#include "HotKeyOperations.h"

//------------------------------------------------------------------------

const size_t START_CONTAINER_SIZE = 100;

//------------------------------------------------------------------------

HotKeyManager::HotKeyManager(void)
:m_next_id(1)
  {
  m_hot_keys.reserve(START_CONTAINER_SIZE);
  }

//------------------------------------------------------------------------

HotKeyManager::~HotKeyManager(void)
  {
  }

//------------------------------------------------------------------------

HotKeyManager& HotKeyManager::GetInstance()
  {
  static HotKeyManager hot_key_manager;
  return hot_key_manager;
  }

//------------------------------------------------------------------------

//------------------------------------------------------------------------
//   Interface
//------------------------------------------------------------------------

bool HotKeyManager::AddHotKey(HotKey::KeyCode i_vk_code, 
                              HotKeyOperation::IOperation * ip_operation /*= 0*/,
                              const std::wstring& i_name /*= std::wstring()*/,
                              HotKey::Modifier i_modifier /*= MOD_NONE*/)
  {
  HotKeyIterator hk_it = GetHotKey(i_vk_code, i_modifier);
  if (hk_it != GetEnd())
    return false;
  
  boost::shared_ptr<HotKey> p_hot_key(new HotKey(m_next_id++, i_vk_code, ip_operation, i_name, i_modifier));
  if (p_hot_key->GetIsRegistered())
    {
    m_hot_keys.push_back(p_hot_key);
    return true;
    }

  --m_next_id;
  return false;
  }

//------------------------------------------------------------------------

HotKeyManager::HotKeyIterator HotKeyManager::GetHotKey(unsigned int i_id)
  {
  HotKeyIterator hk_it = std::find_if(GetBegin(), GetEnd(), HotKeyCompare::CompareByID(i_id));
  return hk_it;
  }

//------------------------------------------------------------------------

HotKeyManager::HotKeyIterator HotKeyManager::GetHotKey(HotKey::KeyCode i_vk_code, HotKey::Modifier i_modifier)
  {
  HotKeyIterator hk_it = std::find_if(GetBegin(), GetEnd(), HotKeyCompare::CompareByKeys(i_vk_code, i_modifier));
  return hk_it;
  }

//------------------------------------------------------------------------

HotKeyManager::HotKeyIterator HotKeyManager::GetHotKey(std::wstring& i_name)
  {
  HotKeyIterator hk_it = std::find_if(GetBegin(), GetEnd(), HotKeyCompare::CompareByName(i_name));
  return hk_it;
  }

//------------------------------------------------------------------------

bool HotKeyManager::RemoveHotKey(HotKeyIterator it_hot_key)
  {
  int hk_id = (*it_hot_key)->GetID();
  if (!(*it_hot_key)->Unregister())
    return false;

  if (hk_id < m_next_id)
    m_next_id = hk_id;
  m_hot_keys.erase(it_hot_key);
  return true;
  }

//------------------------------------------------------------------------
bool HotKeyManager::RemoveHotKey(HotKey::KeyCode i_vk_code, HotKey::Modifier i_modifier)
  {
  HotKeyIterator hk_it = GetHotKey(i_vk_code, i_modifier);
  if (hk_it == GetEnd())
    return false;

  return RemoveHotKey(hk_it);
  }

//------------------------------------------------------------------------

bool HotKeyManager::RemoveHotKey(std::wstring & i_name)
  {
  HotKeyIterator hk_it = GetHotKey(i_name);
  if (hk_it == GetEnd())
    return false;

  return RemoveHotKey(hk_it);
  }

//------------------------------------------------------------------------

void HotKeyManager::Clear()
  {
  while (!m_hot_keys.empty())
    RemoveHotKey(m_hot_keys.begin());
  }

//------------------------------------------------------------------------

size_t HotKeyManager::GetNumberOfRegistered() const
  {
  return m_hot_keys.size();
  }

//------------------------------------------------------------------------

void HotKeyManager::Save(std::wstring i_filename)
  {
  std::string filename(i_filename.begin(), i_filename.end());
  std::ofstream fout(filename.c_str(), std::ios_base::binary);
  boost::archive::binary_oarchive ar(fout);
  HotKeyOperation::RegisterAll(ar);
  ar << m_hot_keys;
  }

//------------------------------------------------------------------------

void HotKeyManager::Load(std::wstring i_filename)
  {
  Clear();

  std::string filename(i_filename.begin(), i_filename.end());
  std::ifstream fin(filename.c_str(), std::ios_base::binary);
  boost::archive::binary_iarchive ar(fin);
  HotKeyOperation::RegisterAll(ar);

  ar >> m_hot_keys;

  for (HotKeyIterator hk_it = GetBegin(); hk_it != GetEnd(); ++hk_it)
    (*hk_it)->Register();
  }

//------------------------------------------------------------------------

//------------------------------------------------------------------------
//   Iterators
//------------------------------------------------------------------------

HotKeyManager::HotKeyIterator HotKeyManager::GetBegin()
  {
  return m_hot_keys.begin();
  }

//------------------------------------------------------------------------

HotKeyManager::HotKeyIterator HotKeyManager::GetEnd()
  {
  return m_hot_keys.end();
  }

//------------------------------------------------------------------------